import wx
import re
import time
import sys
from pyDemin import *
from client import *
from wxPython.lib.dialogs import *
from time import time, sleep


class Console:
    
    def __init__(self,parent):#init des attributs
        self.partie=None
        self.client=None
        self.parent=parent

    def initialisationClient(self,port,host):#initialisation de la liaison client-serveur
        debutClient(port,host,self)

    def affichagePartieDisp(self,nb,parties):#affichage des parties disponibles sur le reseau
        self.nb=nb
        self.parties=parties
        #print self.nb
        #print self.parties

        if nb==0:#s'il n'y a aucune partie disponible sur le reseau
            self.affichagePasParties()
        else:
            self.affichageParties()


    #fonctions pour affichage Console
    def affichagePasParties(self):
        #instructions si il n'y a pas de parties
        print "\n\nIl n'y a pour le moment aucune partie en cours"
        print "Pour jouer, vous devez donc creer une nouvelle partie : il faut donc entrer New ou attendre de nouvelles parties (Refresh)"
        print "NB : pour quitter, entrez Quit"
        pasOk=True
        #on regarde si l'entree n'est pas completement a cote de la plaque
        while pasOk:
             msg = raw_input('>> ')
             if msg=="New":
                 self.nouvellePartie()
                 pasOk=False
             elif msg=="Refresh":                
                 self.Rafraichir()
                 pasOk=False
             elif msg=="Quit":#gere le quitte
                 print "Au revoir"
                 pasOk=False
                 sys.exit(-1)
                 self.parent.Destroy()
             else:#petit message d'erreur 
                 print "Vous n'avez pas entrer une valeur correcte, veuillez recommencer"

    def affichageParties(self):
        #on affiche les parties dispo
        print "\n\nLes parties disponibles actuellement sur le reseau sont : \n"
        for i in range(self.nb):
            print "Numero  : "+str(i)+"\nNombre de joueurs attendus : "+str(self.parties[i][2])+"\nNombre de joueurs deja presents : "+str(self.parties[i][4])+"\nDifficulte : "+str(self.parties[i][3])+"\n"
        #choix de la partie ou creation d'un nouvelle
        print "Choisissez un numero"
        print "Vous pouvez aussi rafraichir l'affichage (Refresh), initialiser une nouvelle partie (New) ou quitter (Quit)"
        pasOk=True
        #on regarde si on envoie pas n'importe quoi
        while pasOk:
            msg = raw_input('>> ')
            if re.search("^[0-9]+$",msg)!=None:
                self.choixPartie(int(msg))
                pasOk=False
            elif msg=="Refresh":
                self.Rafraichir()
                pasOk=False
            elif msg=="New":
                self.nouvellePartie()
                pasOk=False
            elif msg=="Quit":
                print "Au revoir"
                pasOk=False
                sys.exit(-1)
                self.parent.Destroy()
            else:# si on envoie n'importe quoi , petit message d'erreur 
                print msg
                print "Vous n'avez pas entrer une valeur correcte, veuillez recommencer"

    def Rafraichir(self):
        self.client.mySocketEmission.send("listePartiesEnAttente")#on rafraichit : on demande la liste des parties a serveur

    def nouvellePartie(self):
        #instructions pour creer une nouvelle partie
        print "\n\n  Entrez les caracteristiques de la partie"
        print "NB : entrer Quit pour quitter"
        #le pseudo
        print "Votre pseudo"
        msg = raw_input('>> ')
        #si il decide de quitter a ce moment la 
        if msg=="Quit":
            print "Au revoir"
            pasOk=False
            sys.exit(-1)
            self.Destroy()
        else:
            self.nomJoueur=msg
        #le Nom de la nouvelle partie
        print "\nNom de la partie"
        msg = raw_input('>> ')
        #si il decide de quitter a ce moment la 
        if msg=="Quit":
            print "Au revoir"
            sys.exit(-1)
            self.parent.Destroy()
        else:
            self.nomPartie=msg
        #Le nombre de joueurs max dans la partie nouvellement cree
        print "\nNombre de joueurs attendus (entre 2 et 8)"
        pasOk=True
        #on attend le nombre de joueurs, juqu'a ce que l'utilisateur rentre un nombre utilisable
        while pasOk:
            msg = raw_input('>> ')
            if re.search("^[0-9]+$",msg)!=None:
                self.nbJoueursAttendus=int(msg)
                pasOk=False
            elif msg=="Quit":
                print "Au revoir"
                pasOk=False
                sys.exit(-1)
                self.Destroy()
            else: #si l'utilisateur n'a pas rentre un nombre entre 1 et 8 :
                print "Vous n'avez pas entre une valeur correcte, veuillez recommencer"
        # la difficulte de la partie
        print "\nDifficulte (Facile, Moyen ou Difficile)"
        pasOk=True
        #on attend le nombre de joueurs, jusqu'a ce que l'utilisateur rentre une difficulte utilisable
        while pasOk:
            msg = raw_input('>> ')
            if msg=="Quit":
                print "Au revoir"
                sys.exit(-1)
                pasOk=False
                self.Destroy()
            elif msg=="Facile" or msg=="Moyen" or msg=="Difficile":
                self.difficulte=msg
                pasOk=False
            else:#si on se trompe
                print "Vous n'avez pas entre une valeur correcte, veuillez recommencer"
        self.client.mySocketEmission.send("partie\n"+self.nomPartie+","+str(self.nbJoueursAttendus)+","+str(self.difficulte)+","+str(1)+","+self.nomJoueur)#on envoie les infos de la nouvelle partie au serveur 
        #message on attend que le nombre de joueurs attendus soit atteint
        print "Vous devez maintenant attendre que "+str(self.nbJoueursAttendus-1)+" joueur(s) rejoignent cette partie\n"
        
            
    def choixPartie(self,num):
        #infos sur la partie rejointe
        print "\n\nVous avez choisi la partie :"
        print "Numero  : "+str(num)+"\nNombre de joueurs attendus : "+str(self.parties[num][2])+"\nNombre de joueurs deja presents : "+str(self.parties[num][4])+"\nDifficulte : "+str(self.parties[num][3])+"\n"
        #Pseudo choisi par le joueur entrant
        print "Entrez votre pseudo"
        print "NB : Vous pouvez aussi quitter (Quit)"
        msg = raw_input('>> ')
        if msg=="Quit":#si on s'est trompe de partie 
            print "Au revoir"
            pasOk=False
            self.client.Termine=True
            self.parent.Destroy()
            sys.exit(-1)
        else:
            self.nomJoueur=msg
        #on envoie les infos au serveur ( numero de la partie + nom joueur )
        self.client.mySocketEmission.send("numPartieChoisie\n"+str(self.parties[num][0])+"\n"+"nomJoueur\n"+self.nomJoueur)
        #on recupere des infos :
        self.nomPartie=self.parties[num][1]
        self.nbJoueursAttendus=self.parties[num][2]
        self.difficulte=self.parties[num][3]
        self.Joueurs=self.parties[num][5::]
        self.Joueurs.append(self.nomJoueur)
        self.partie=[self.nomPartie,self.nbJoueursAttendus,self.difficulte,self.Joueurs]
        #message: on affiche le nombre de joueurs encore attendus pour commencer la partie
        if self.parties[num][2]!=self.parties[num][4]+1:
            print "Vous devez attendre encore "+str(self.parties[num][2]-self.parties[num][4]-1)+" joueurs avant de debuter la partie"

    def debutPartie(self,listeJoueurs):
        #on met a jours les infos de la partie
        self.Joueurs=listeJoueurs
        self.partie=[self.nomPartie,len(listeJoueurs),self.difficulte,self.Joueurs]
        self.jeu=DeminConsolReseau(self.partie,self.nomJoueur,self)

    def Matrice(self,matrice):
        #on appelle la fonction matrice sur la matrice
        self.jeu.matrice(matrice)

    def Tour(self):
        #on appelle buffer ( graphique )
        self.jeu.atoi=True
        self.jeu.atoiAV=False
        self.jeu.buffer()

    def modifCompteur(self,nomJoueur,newVal):
        #on met a jour les compteurs
        self.jeu.modifCompteur(nomJoueur,newVal)

    def decouvrement(self,clic,typ,nom):
        #on decouvre les cases vides autour du clic
        self.jeu.decouvrir(clic[0],clic[1],typ)

    def aPerdu(self,joueurPerdant):
        #on vire le joueur de la liste et on affiche le joueur qui perd
        print joueurPerdant+" a perdu. Le jeu continue"
        index=self.jeu.nomJoueurs.index(joueurPerdant)
        self.jeu.nomJoueurs.pop(index)

    def finPartie(self,joueursGagnants):
        #on dit au gagnant l'heureuse nouvelle
        if self.nomJoueur in joueursGagnants:
            print "Vous avez gagne"
        else:
            #on annonce (un peu brutalement) aux autres la mauvaise nouvelle
            #on conjugue selon le nombre de gagnants
            if len(joueursGagnants)==1:
                print joueursGagnants+" a gagne. Vous avez donc perdu"
            else:
                for i in range(len(joueursGagnants)-1):
                    s+=joueursGagnants[i]+", "
                s+=joueursGagnants[len(joueursGagnants)-1]+" ont gagne. Vous avez donc perdu"
        self.client.Termine=True
        self.parent.Destroy()
        sys.exit(-1)
            
    def quitte(self,nomJoueur):
        #permet a "nomjoueur" de quitter la partie
        print nomJoueur+" a quitte la partie. Le jeu continue"
        index=self.jeu.nomJoueurs.index(nomJoueur)
        self.jeu.nomJoueurs.pop(index)

class ReseauFrame(wx.Frame):
    def __init__(self, parent, ID, title, pos=wx.DefaultPosition,size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
        wx.Frame.__init__(self, parent, ID, title, pos, size, style)
        self.SetAutoLayout(True)
        self.Panel=None
        
        NewGame = wx.Button(self,1,"Partie en Solo",(10,10),(150,100))
        self.Bind(wx.EVT_BUTTON,self.fnewgame, id=1)

        cb=wx.StaticText(self,23,"Difficulte",(150,345),size=(260,30))

    def fnewgame(self,evt):
        print "fnewgame"
        

class DeminConsolReseau:

    def __init__(self,partie,nomJ,parent):
        self.wm=30
        self.hm=30

        #recuperation des donnees relatives a la partie
        self.nomPartie=partie[0]
        self.nbJoueurs=partie[1]
        self.difficulte=partie[2]
        self.nomJoueurs=partie[3]
        self.compteurs=[0]*self.nbJoueurs
        self.nomJ=nomJ
        
        #determine si joueur doit demarrer la partie ou pas
        if re.search("^[0-9]",self.difficulte)!=None:
            self.difficulte=int(self.difficulte)
            self.nb=self.difficulte*45-(self.difficulte-1)*5#determination du nb de mines dans le jeu selon la difficulte
        elif self.difficulte=="Facile":
            self.nb=45
        elif self.difficulte=="Moyen":
            self.nb=85
        else:
            self.nb=120

        self.game=pyDemin(self.wm,self.hm,self.nb)#initialisation du jeu en lui-meme

        self.parent=parent

        self.premier=False
        self.atoi=False
        self.atoiAV=False
        if self.nomJ==self.nomJoueurs[0]:
            self.premier=True
            print "premier"
        else:
            print "pas premier"
            self.init_buffer()
        self.test=True

    def init_buffer(self):
        s="   "
        for j in range(self.wm):
            if j>=10:
                s+=" "+str(j)+" "
            else:
                s+=" "+str(j)+"  " 
        s+="\n"
        for j in range(self.wm):
            s+="===="
        s+="==="
        s+="\n"
        for i in range(self.hm):
            if i>=10:
                s+=str(i)+"||"
            else:
                s+=" "+str(i)+"||"
            for j in range(self.wm):
                s+=" . |"
            s+="\n"
            for j in range(self.wm):
                s+="----"
            s+="---"
            s+="\n"
        print s
        self.Compteurs()
        #affichage de la grille en console
        if self.premier:
            self.pourClic()
        else:
            print "Attente des jeux des autres joueurs"
            

    def pourClic(self):
        if not self.premier:
            #on demande le type de clic ( droit ou gauche ) mais en anglais
            print "\nChoisissez un type de 'clic' (left ou right)"
            print "NB : Quit pour quitter"
            pasOk=True
            #on attend que le joueur choisisse
            while pasOk:
                msg = raw_input('>> ')
                if msg=="Quit":
                    pasOk=False
                    self.pourQuitter()
                elif msg=="left":
                    typ=msg
                    pasOk=False
                elif msg=="right":
                    typ=msg
                    pasOk=False
                else:#si il se trompe
                    print "Vous n'avez pas entre une valeur correcte"
        else:
            typ="left"
        #on demande les coordonnees de clics
        print "\nChoisissez les coordonnees du 'clic' (x,y avec x en ligne et y en colonne)"
        print "NB : Quit pour quitter"
        pasOk=True
        #on attend les coordonnees
        while pasOk:
            msg = raw_input('>> ')
            if msg=="Quit":
                pasOk=False
                self.pourQuitter()
            elif re.search("^[0-9]+,[0-9]+$",msg)!=None:#on verifie que les entrees du joueur soient valides
                l=msg.split(",")
                x=int(l[0])
                y=int(l[1])
                if x<0 or self.wm<=x or y<0 or self.hm<=y:#si il a clique en dehors de la grille
                    print "Vous n'avez pas entre une valeur correcte"
                else:
                    pasOk=False
                    self.atoi=False
                    self.atoiAV=True
                    #on appelle la fonction clic qui gere tout ca
                    self.clic(x,y,typ)
            else:#si il a marque autre chose que des coordonnes
                print "Vous n'avez pas entre une valeur correcte"

    def clic(self,x,y,typ):
        tt=True
        if typ=="left":
            if self.premier:#si le joueur doit demarrer la partie
                self.game.debut(x,y)#1er clic, qui ne doit pas etre sur une bombe
                matrice=self.transfoMatrice()#recuperation de la matrice des bombes
            #envoi au serveur qui la transmet aux autres joueurs
                self.parent.client.mySocketEmission.send("matrice\n"+matrice)
                self.premier=False
                self.test=True
            else:
                # si on clique sur une bombe
                if self.game.mine[y*self.game.w+x]==-1:
                    print  "Vous avez choisi une case avec une bombe, vous avez perdu"
                    if self.nbJoueurs==2:#si il n'y avait que deux joueurs la partie est terminee
                        i=self.nomJoueurs.index(self.nomJ)
                        self.parent.client.mySocketEmission.send("finPartie\n"+self.nomJoueurs[1-i])#on annonce la fin de la partie a tout le monde
                    else:
                        #si il y a plus de deux joueurs un seul perd
                        self.parent.client.mySocketEmission.send("aPerdu\n"+self.nomJ)
                    self.test=True
                    tt=False
                    self.parent.client.Termine=True
                    self.parent.parent.Destroy()
                    sys.exit(-1)
                else:
                    #on decouvre tout ce qu'il y a autour 
                    self.game.decouvre(x,y)
                    self.test=True
        else:
            #clik droit :
            i=self.nomJoueurs.index(self.nomJ)
            #si on clique droit sur une mine
            if self.game.mine[y*self.game.w+x]==-1:
                #on marque la mine et on incremente le compteur
                self.game.aamine(x,y)
                self.compteurs[i]+=2
                self.test=True
            else:
                #si on clique droit a cote d'une mine
                print "Il n'y a pas de bombe ici\nVous passez donc votre tour\n"
                self.compteurs[i]-=1
                self.test=False
            #on envoie modifs compteur au serveur
            self.parent.client.mySocketEmission.send("modificationCompteur\n"+self.nomJ+"\n"+str(self.compteurs[i]))
            
        if tt:
            self.x=x
            self.y=y
            self.typ=typ
            #on dessine le buffer
            self.buffer()

    def transfoMatrice(self):
        matrice=self.game.mine
        s=""
        if len(matrice)!=self.wm*self.hm:
            print "soucis"
            sys.exit(-1)
        for i in range(len(matrice)-1):
            s+=str(matrice[i])+","
        s+=str(matrice[i])
        return s
            

    def buffer(self):
        #fonction de dessin de la grille updatee normalement
        t=True
        nb=0
        mm=0
        mT=0
        s="    "
        for j in range(self.wm):
            if j>=10:
                s+=" "+str(j)+" "
            else:
                s+=" "+str(j)+"  "
        s+="\n"
        for j in range(self.wm):
            s+="===="
        s+="==="
        s+="\n"
        for i in range(self.hm):
            if i>=10:
                s+=str(i)+"||"
            else:
                s+=" "+str(i)+"||"
            for j in range(self.wm):
                if self.game.dec[j*self.game.w+i]==0:
                    s+=" . |"
                elif self.game.dec[j*self.game.w+i]==-1:
                    if self.game.mine[j*self.game.w+i]==-1:
                        s+=" x |"
                        mm+=1
                    else:
                        t=False
                        print "Pb traitement pas bombe"
                        s+=" . |"
                elif self.game.dec[j*self.game.w+i]==-2:
                    s+=" * |"
                    mT+=1
                elif self.game.mine[j*self.game.w+i]==-1:
                    t=False
                    print "Pb traitement"
                else:
                    k=self.game.grille[j*self.game.w+i]
                    if k!=0:
                        s+=" "+str(k)+" |"
                    else:
                        s+="   |"
                    nb+=1
            s+="\n"
            for j in range(self.wm):
                s+="----"
            s+="---"
            s+="\n"
        
        if nb==self.hm*self.wm-self.nb:
            t=False
            index=self.nomJoueurs.index(self.nomJ)
            if self.compteurs[index]==max(self.compteurs):
                print "Vous avez gagne"
                self.parent.client.mySocketEmission.send("finPartie\n"+self.nomJ)
            else:
                print "Vous avez perdu"
                ind=self.nomJoueurs.index(max(self.compteurs))
                self.parent.client.mySocketEmission.send("finPartie\n"+self.nomJoueurs[ind])
         
        if t:
            print s+"\n\n"
            self.Compteurs()
            if self.test:
                if self.atoiAV:
                    self.parent.client.mySocketEmission.send("clic\n"+str(self.x)+","+str(self.y)+","+self.typ)
                    self.atoiAV=False
                    print "Attente du jeu des autres joueurs"
                elif self.atoi:
                    self.pourClic()
                else:
                    print "Attente du jeu des autres joueurs"
            else:
                self.parent.client.mySocketEmission.send("pass")
                self.test=True

    
    def Compteurs(self):
        print "Etats des autres joueurs"
        for i in range(self.nbJoueurs):
            print self.nomJoueurs[i]+" : "+str(self.compteurs[i])


    def matrice(self,matrice):
        self.game.mine=matrice

    def modifCompteur(self,nomJoueur,newVal):
        index=self.nomJoueurs.index(nomJoueur)
        self.compteurs[index]=newVal
               
    def decouvrir(self,x,y,typ):
        if typ=="left":
            self.game.decouvre(x,y)
        else:
            self.game.aamineAJ(x,y)
        self.x=x
        self.y=y
        self.typ=typ
        self.buffer()

    def pourQuitter(self):
        print "Etez-vous sur de vouloir quitter la partie en cours? (oui/non)"
        pasOk=True
        while pasOk:
            msg = raw_input('>> ')
            if msg=="oui":
                print "Au revoir"
                self.parent.client.mySocketEmission.send("quitte\n"+self.nomJ)
                self.parent.client.Termine=True
                self.parent.parent.Destroy()
                sys.exit(-1)
                pasOk=False
            elif msg=="non":
                pasOk=False
            else:
                print "Vous n'avez pas entre une valeur correcte"

